package com.jy.rhin.domain.notification.topic;

import com.jy.rhin.domain.exception.RhinInfraErrorType;
import com.jy.rhin.domain.notification.topic.entity.TopicDO;
import com.jy.rhin.domain.notification.topic.entity.TopicQueryFilterVO;
import com.jy.rhin.domain.notification.topic.entity.TopicQueryVO;
import com.jy.rhin.infra.uitl.Asserts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author WeiQ
 * @date 2022/6/28 15:36
 * 通知主题管理域服务
 */
@Slf4j
@Service
public class TopicDomainService {

    @Resource
    TopicDao topicDao;

    /**
     * 创建一个主题
     * 1、表达式不能重复
     * 2、主题预存查询及其过滤条件不能为空
     * 3、发布者必须存在
     *
     * @param topicDO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Long create(TopicDO topicDO) {
        TopicDO origin = topicDao.queryByTopicExp(topicDO.getTopicExp());
        //更新时判断主题记录是否存在
        Asserts.isFalse(Objects.nonNull(topicDO.getId()) && Objects.isNull(origin), RhinInfraErrorType.PARTICIPANT_NOT_FOUND);
        //根据 主题表达式 查询到主题记录，且不是当前编辑的记录，则说明主题重复
        Asserts.isFalse(Objects.nonNull(origin) && !Objects.equals(origin.getId(), topicDO.getId()), RhinInfraErrorType.TOPIC_EXP_EXISTS);
        //主题预存查询及其过滤条件不能为空
        List<TopicQueryVO> queryList = topicDO.getQueryList();
        if(!CollectionUtils.isEmpty(queryList)){
            //同一主题下不能存在相同的预存查询函数表达式
            checkQueryExpRepeat(queryList);
            for (TopicQueryVO topicQueryVO : queryList) {
                List<TopicQueryFilterVO> filterList = topicQueryVO.getFilterList();
                Asserts.notEmpty(filterList, RhinInfraErrorType.TOPIC_QUERY_OR_FILTER_EMPTY);
                //同一主题同一预存查询函数不能存在相同的过滤条件表达式
                checkQueryFilterExpRepeat(filterList);
            }
        }
        topicDao.save(topicDO);
        return topicDO.getId();
    }

    /**
     * 根据主题表达式查询主题
     * @param topicExp
     * @return
     */
    public TopicDO queryByTopicExp(String topicExp) {
        return topicDao.queryByTopicExp(topicExp);
    }

    /**
     * 验证过滤条件表达式是否重复
     * @param filterList
     */
    private void checkQueryFilterExpRepeat(List<TopicQueryFilterVO> filterList) {
        Set<String> filterExpList = filterList.stream().map(TopicQueryFilterVO::getFilterExp).collect(Collectors.toSet());
        Asserts.equals(filterList.size(), filterExpList.size(), RhinInfraErrorType.TOPIC_QUERY_FILTER_EXP_REPEAT);
    }

    /**
     * 验证查询函数表达式是否重复
     * @param queryList
     */
    private void checkQueryExpRepeat(List<TopicQueryVO> queryList) {
        Set<String> queryExpList = queryList.stream().map(TopicQueryVO::getQueryExp).collect(Collectors.toSet());
        Asserts.equals(queryList.size(), queryExpList.size(), RhinInfraErrorType.TOPIC_QUERY_EXP_REPEAT);
    }
}
